package config

import (
	"context"
	"errors"
	"gitcode.com/G-YT/ANN/server/global"
	"gitcode.com/G-YT/ANN/server/model/common/request"
	"gitcode.com/G-YT/ANN/server/model/config"
	configReq "gitcode.com/G-YT/ANN/server/model/config/request"
	"gitcode.com/G-YT/ANN/server/utils"
	"gorm.io/gorm"
)

type ConfigService struct {
}

// CreateConfig 创建Config记录
// Author [piexlmax](https://github.com/piexlmax)
func (c *ConfigService) CreateConfig(appConfig *config.Config) (err error) {
	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		err = global.GVA_DB.Create(appConfig).Error
		keyName := "Config:redis"
		key := appConfig.Key
		value := appConfig.Value
		if err = global.GVA_REDIS.HSet(context.Background(), keyName, key, value).Err(); err != nil {
			return err
		}
		return nil
	})
}

// DeleteConfig 删除Config记录
// Author [piexlmax](https://github.com/piexlmax)
func (c *ConfigService) DeleteConfig(appConfig config.Config) (err error) {
	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		if err := global.GVA_DB.First(&appConfig, appConfig.ID).Error; err != nil {
			return err
		}
		if err = global.GVA_DB.Delete(&appConfig).Error; err != nil {
			return err
		}
		keyName := "Config:redis"
		key := appConfig.Key
		if err = global.GVA_REDIS.HDel(context.Background(), keyName, key).Err(); err != nil {
			return err
		}
		return nil
	})
}

// DeleteConfigByIds 批量删除Config记录
// Author [piexlmax](https://github.com/piexlmax)
func (c *ConfigService) DeleteConfigByIds(ids request.IdsReq) (err error) {
	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		var configs []config.Config
		var keys []string
		if err := global.GVA_DB.Select("key").Where("id IN (?)", ids.Ids).Find(&configs).Error; err != nil {
			return err
		}
		if err = global.GVA_DB.Delete(&[]config.Config{}, "id in ?", ids.Ids).Error; err != nil {
			return err
		}
		for _, config := range configs {
			keys = append(keys, config.Key)
		}
		keyName := "Config:redis"
		if err = global.GVA_REDIS.HDel(context.Background(), keyName, keys...).Err(); err != nil {
			return err
		}
		return nil
	})
}

// UpdateConfig 更新Config记录
// Author [piexlmax](https://github.com/piexlmax)
func (c *ConfigService) UpdateConfig(appConfig config.Config) (err error) {
	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		err = global.GVA_DB.Save(&appConfig).Error
		keyName := "Config:redis"
		key := appConfig.Key
		value := appConfig.Value
		if err = global.GVA_REDIS.HSet(context.Background(), keyName, key, value).Err(); err != nil {
			return err
		}
		return nil
	})
}

// GetConfig 根据id获取Config记录
// Author [piexlmax](https://github.com/piexlmax)
func (c *ConfigService) GetConfig(id uint) (appConfig config.Config, err error) {
	err = global.GVA_DB.Where("id = ?", id).First(&appConfig).Error
	return
}

// GetConfigInfoList 分页获取Config记录
// Author [piexlmax](https://github.com/piexlmax)
func (c *ConfigService) GetConfigInfoList(info configReq.ConfigSearch) (list []config.Config, total int64, err error) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	// 创建db
	db := global.GVA_DB.Model(&config.Config{})
	var appConfigs []config.Config
	// 如果有条件搜索 下方会自动创建搜索语句
	if info.StartCreatedAt != nil && info.EndCreatedAt != nil {
		db = db.Where("created_at BETWEEN ? AND ?", info.StartCreatedAt, info.EndCreatedAt)
	}
	if info.Key != "" {
		db = db.Where("key = ?", info.Key)
	}
	err = db.Count(&total).Error
	if err != nil {
		return
	}

	err = db.Limit(limit).Offset(offset).Find(&appConfigs).Error
	return appConfigs, total, err
}

// GetAllConfigList 分页获取Config记录
// Author [piexlmax](https://github.com/piexlmax)
func (c *ConfigService) GetAllConfigList() (list []config.Config, err error) {
	err = global.GVA_DB.Model(&config.Config{}).Find(&list).Error
	return
}

// GetRedisByField 根据字段获取Redis
func (c *ConfigService) GetRedisByField(fields []string) (result map[string]string, err error) {
	key := "Config:redis"
	isExists, _ := global.GVA_REDIS.Exists(context.Background(), key).Result()
	if isExists == 0 {
		var configs []config.Config
		if err = global.GVA_DB.Model(&config.Config{}).Find(&configs).Error; err != nil {
			return nil, err
		}
		configData := make(map[string]string)
		for _, v := range configs {
			configData[v.Key] = v.Value
		}
		err = global.GVA_REDIS.HMSet(context.Background(), key, configData).Err()
		result = make(map[string]string)
		for _, field := range fields {
			result[field] = configData[field]
		}
		return result, nil
	}
	// 如果缓存存在，从缓存中获取数据
	result = make(map[string]string)
	values, err := global.GVA_REDIS.HMGet(context.Background(), key, fields...).Result()
	if err != nil {
		return nil, err
	}
	for i, field := range fields {
		result[field] = values[i].(string)
	}
	return result, nil
}

// GetCountRedis 根据字段获取Redis
func (c *ConfigService) GetCountRedis(fields []string) (result map[string]interface{}, err error) {
	key := "Count:redis"
	isExists, _ := global.GVA_REDIS.Exists(context.Background(), key).Result()
	if isExists == 0 {
		err := utils.UpdateCountData()
		if err != nil {
			return nil, errors.New("獲取統計數據失敗")
		}
		// 如果缓存存在,从缓存中获取数据
		result = make(map[string]interface{})
		values, err := global.GVA_REDIS.HMGet(context.Background(), key, fields...).Result()
		if err != nil {
			return nil, err
		}
		for i, field := range fields {
			result[field] = values[i].(string)
		}
	}
	// 如果缓存存在，从缓存中获取数据
	result = make(map[string]interface{})
	values, err := global.GVA_REDIS.HMGet(context.Background(), key, fields...).Result()
	if err != nil {
		return nil, err
	}
	for i, field := range fields {
		result[field] = values[i].(string)
	}
	return result, nil
}
